第 13 天,我開始將 HTML 程式碼重構為可重用的 CoffeePlan
元件。該元件將接受一個 name
輸入,並在 HTML 模板中顯示該輸入值。
<div class="content">
<h1 class="title">Coffee Plans</h1>
<h2 class="subtitle">We travel the world to source the very best single origin coffee for you</h2>
<div class="plans">
<div class="plan">
<div class="description">
<span class="title"> The Single </span>
</div>
</div>
<div class="plan">
<div class="description">
<span class="title"> The Curious </span>
</div>
</div>
<div class="plan">
<div class="description">
<span class="title"> The Addict </span>
</div>
</div>
</div>
</div>
以下的 HTML 區塊重複出現四次,僅標題不同,因此可以將其抽取為 CoffeePlan 元件:
<div class="plan">
<div class="description">
<span class="title"> The Single </span>
</div>
</div>
<script setup lang="ts"></script>
<template>
<div class="plan">
<div class="description">
<span class="title"> The Single </span>
</div>
</div>
</template>
<script setup lang="ts">
import CoffeePlan from './components/CoffeePlan.vue'
</script>
<template>
<div class="content">
<h1 class="title">Coffee Plans</h1>
<h2 class="subtitle">We travel the world to source the very best single origin coffee for you</h2>
<div class="plans">
<CoffeePlan />
<CoffeePlan />
<CoffeePlan />
<CoffeePlan />
</div>
</div>
</template>
新建 lib/coffee-plan.svelte
檔案並更新模板:
<script lang="ts"></script>
<div class="plan">
<div class="description">
<span class="title"> The Single </span>
</div>
</div>
從 lib/index.ts
匯出此元件:
export * from './coffee-plan.svelte';
在 +page.svelte
中匯入 CoffeePlan:
<script lang="ts">
import CoffeePlan from '$lib/coffee-plan.svelte';
</script>
<template>
<div class="content">
<h1 class="title">Coffee Plans</h1>
<h2 class="subtitle">We travel the world to source the very best single origin coffee for you</h2>
<div class="plans">
<CoffeePlan />
<CoffeePlan />
<CoffeePlan />
<CoffeePlan />
</div>
</div>
</template>
建立新的 CoffeePlanComponent
:
ng g c coffeePlan
@Component({
selector: 'app-coffee-plan',
imports: [],
template: `
<div class="plan">
<div class="description">
<span class="title"> The Single </span>
</div>
</div>
`,
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class CoffeePlanComponent {}
在 app.component.ts
中匯入 CoffeePlanComponent
:
import { CoffeePlanComponent } from './coffee-plan/coffee-plan.component';
@Component({
selector: 'app-root',
imports: [CoffeePlanComponent],
template: `
<div class="content">
<h1 class="title">Coffee Plans</h1>
<h2 class="subtitle">We travel the world to source the very best single origin coffee for you</h2>
<div class="plans">
<app-coffee-plan />
<app-coffee-plan />
<app-coffee-plan />
<app-coffee-plan />
</div>
</div>
`,
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class AppComponent {}
name
prop。defineProps 會自動導入,無需明確匯入。<script setup lang="ts">
defineProps({
name: {
type: String,
default: 'Default Plan',
},
})
</script>
<template>
<div class="plan">
<div class="description">
<span class="title"> {{ name }} </span>
</div>
</div>
</template>
<script setup lang="ts">
import CoffeePlan from './components/CoffeePlan.vue'
import { ref } from 'vue'
const plans = ref(["The Single", "The Curious", "The Addict", "The Hacker"])
</script>
<template>
<div class="content">
<h1 class="title">Coffee Plans</h1>
<h2 class="subtitle">We travel the world to source the very best single origin coffee for you</h2>
<div class="plans">
<CoffeePlan v-for="plan in plans" :key="plan" :name="plan" />
</div>
</div>
</template>
name
prop。無需匯入即可使用 $props。<script lang="ts">
interface Props {
name: string
}
const { name = 'Default Plan' } = $props();
</script>
<div class="plan">
<div class="description">
<span class="title">{name}</span>
</div>
</div>
<script lang="ts">
import CoffeePlan from '$lib/coffee-plan.svelte';
const plans = $state(['The Single', 'The Curious', 'The Addict', 'The Hacker']);
</script>
<template>
<div class="content">
<h1 class="title">Coffee Plans</h1>
<h2 class="subtitle">We travel the world to source the very best single origin coffee for you</h2>
<div class="plans">
{#each plans as plan (plan)}
<CoffeePlan plan={name} />
{/each}
</div>
</div>
</template>
name
的 signal 輸入:@Component({
selector: 'app-coffee-plan',
imports: [],
template: `
<div class="plan">
<div class="description">
<span class="title">{{ name() }}</span>
</div>
</div>
`,
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class CoffeePlanComponent {
name = input('Default Plan');
}
import { CoffeePlanComponent } from './coffee-plan/coffee-plan.component';
@Component({
selector: 'app-root',
imports: [CoffeePlanComponent],
template: `
<div class="content">
<h1 class="title">Coffee Plans</h1>
<h2 class="subtitle">We travel the world to source the very best single origin coffee for you</h2>
<div class="plans">
@for (plan of plans(); track plan) {
<app-coffee-plan [name]="plan" />
}
</div>
</div>
`,
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class AppComponent {
plans = signal(['The Single', 'The Curious', 'The Addict', 'The Hacker']);
}
我們已成功建立一個可重用的 CoffeePlan 元件,並匯入到 App 元件中以顯示不同的方案。